const express = require("express")
const router = express.Router()
const {Post, Tag, User, Comment} = require("../models")
const {Op, col} = require("sequelize")
const {Forbidden, NotFound} = require("http-errors")

const userAuth = require("../middlewares/user-auth")
const {success, failure} = require("../utils/response")

/**
 * 分类列表
 */
router.get("/", async (req, res, next) => {
    try {
        const query = req.query
        const currentPage = Math.abs(Number(query.currentPage)) || 1
        const pageSize = Math.abs(Number(query.pageSize)) || 10
        const offset = (currentPage - 1) * pageSize


        const {count, rows} = await Post.findAndCountAll({
            order: [['id', 'DESC']],
            attributes: {exclude: ['UserId']},
            include: [
                {
                    model: User,
                    as: 'user',
                    attributes: ['id', 'name', 'avatar']
                },
            ],
            limit: pageSize,
            offset: offset
        })
        success(res, "查询文章列表成功", {
            post: rows,
            pagination: {
                currentPage,
                pageSize,
                total: count
            }
        })
    } catch(err) {
        console.log(err)
        next(err)
    }
})

/**
 * 帖子详情
 */
router.get("/:id", async (req, res, next) => {
    try {
        const {id} = req.params
        const post = await Post.findByPk(id, {
            attributes: {exclude: ['UserId']},
            include: [
                {
                    model: User,
                    as: 'user',
                    attributes: ['id', 'name', 'avatar']
                },
                {
                    model: Tag,
                    as: 'beTag',
                    attributes: ['id', 'name'],
                    through: {
                        attributes: []
                    }
                }
            ]
        })
        success(res, "查询成功", {post})
    } catch (err) {
        console.log(err)
        next(err)
    }
})

// 发布帖子
router.post("/", userAuth, async (req, res) => {
    try {
        const userId = req.userId
        const {title, content, cover, categoryId} = req.body
        const post = await Post.create({
            title,
            content,
            cover,
            userId,
            categoryId
        })

        success(res, "创建文章成功", {post})

    } catch(err) {
        failure(res, err)
    }
})

/**
 * 删除帖子
 */
router.delete("/:id", userAuth, async (req, res) => {
    try {
        const {id} =  req.params
        const userId = req.userId

        const post = await Post.findByPk(id)

        if(!post) {
            throw new NotFound("文章未找到")
        }

        if(post.userId !== Number(userId)) {
            throw new Forbidden("无权限删除该文章")
        }

        await post.destroy()

        success(res, "删除文章成功")
    } catch(err) {
        failure(res, err)
    }
})

/**
 * 获取一级评论
 */
router.get("/:id/comment", async (req, res, next) => {
    try {
        const {id} = req.params

        const currentSize = Math.abs(Number(req.query.currentSize)) || 1
        const pageSize = Math.abs(Number(req.query.pageSize)) || 10

        const result = await getTopLevelComments(id, currentSize, pageSize)

        success(res, "查询评论成功", {result})
    } catch(err) {
        console.log(err)
        next(err)
    }
})

/**
 * 获取二级评论
 */
router.get("/:id/replies", async (req, res, next) => {
    try {
        const {id} = req.params
        const excludeId = req.query.excludeId || null
        const currentSize = Math.abs(Number(req.query.currentSize)) || 1
        const pageSize = Math.abs(Number(req.query.pageSize)) || 10

        const result = await getNestedReplies(id, currentSize, pageSize, excludeId)

        success(res, "查询评论成功", {result})
    } catch(err) {
        console.log(err)
        next(err)
    }
})

/**
 * 获取一级评论
 * @param postId
 * @param page
 * @param pageSize
 * @returns {Promise<{pagination: {currentPage: number, pageSize: number, total: GroupedCountResultItem[]}, comments: Awaited<*&{replyStats: {total: *, remaining: number}, replyPreview: null|{id: *, content: *, createdAt: *, user: {id: *, name: *, avatar: *}}}>[]}>}
 */
async function getTopLevelComments(postId, page = 1, pageSize = 10) {
    const offset = (page - 1) * pageSize

    const total = await Comment.count({
        where: {
            postId
        }
    })
    const comments = await Comment.findAll({
        attributes: {exclude: ['UserId', 'postId']},
        where: {
            postId,
            parentId: null
        },
        include: [
            {
                model: User,
                as: 'user',
                attributes: ['id', 'name', 'avatar']
            }
        ],
        order: [['createdAt', "ASC"]],
        offset,
        limit: pageSize
    })

    const enhancedComments = await Promise.all(
        comments.map(async (comment) => {
            const replyStats = await getReplyStats(comment.id)
            const replyPreview = await getFirstReply(comment.id) || null

            return {
                ...comment.toJSON(),
                replyStats,
                excludedReplyId: replyPreview?.id || null,
                replyPreview
            };

        })
    )
    return {
        pagination: {
            currentPage: page,
            pageSize,
            total
        },
        comments: enhancedComments
    }
}

/**
 * 获取一级评论的回复统计
 * @param rootId
 * @returns {Promise<{total: GroupedCountResultItem[], remaining: (number|number)}>}
 */
async function getReplyStats(rootId) {
    const total = await Comment.count({
        where: {rootId}
    })
    return {
        total,
        remaining: total > 0 ? total - 1 : 0
    }
}

/**
 * 获取第一条二级评论（按时间最早）
 * @param rootId
 * @returns {Promise<{id, content: (string|string|DocumentFragment|*), createdAt, user: {id, name, avatar: ({type: *}|*)}}|null>}
 */
async function getFirstReply(rootId) {
    const reply = await Comment.findOne({
        where: {rootId},
        include: [
            {
                model: User,
                as: 'user',
                attributes: ['id', 'name', 'avatar']
            }
        ],
        order: [['createdAt', 'ASC']]
    })

    if (!reply) return null;

    return {
        id: reply.id,
        content: reply.content,
        createdAt: reply.createdAt,
        user: {
            id: reply.user.id,
            name: reply.user.name,
            avatar: reply.user.avatar
        }
    }
}

/**
 * 获取二级评论
 * @param rootId
 * @param page
 * @param pageSize
 * @param excludeId
 * @returns {Promise<{rootId, list: any[], pagination: {page, pageSize, total: number, hasMore: boolean}}>}
 */
async function getNestedReplies(rootId, page, pageSize, excludeId = null) {
    const offset = (page - 1) * pageSize


    const where = { rootId };
    if (excludeId) {
        where.id = {
            [Op.ne]: excludeId
        }
    }

    const {count: total, rows: replies} = await Comment.findAndCountAll({
        where,
        include: [
            {
                model: User,
                as: 'user',
                attributes: ['id', 'name', 'avatar']
            },
            {
                model: Comment,
                as: 'parent',
                attributes: ['id'],
                include: [
                    {
                        model: User,
                        as: 'user',
                        attributes: ['id', 'name', 'avatar']
                    }
                ]
            }
        ],
        order: [['createdAt', 'ASC']],
        offset,
        limit: pageSize
    })


    const formattedReplies = replies.map(reply => {
        const replyData = reply.toJSON()

        if(reply.level === 3 && reply.parent) {
            replyData.replyTarget = {
                id: reply.parent.id,
                name: reply.parent.name,
                avatar: reply.parent.avatar
            }
        }

        delete replyData.parent
        return replyData
    })

    return {
        rootId,
        list: formattedReplies,
        pagination: {
            page,
            pageSize,
            total,
            hasMore: (offset + pageSize) < total
        }
    }
}

module.exports = router

